// Copyright (c) 2010, Anthony Cassidy
// All rights reserved.
// 
// Redistribution and use in source and binary forms, with or without modification, are 
// permitted provided that the following conditions are met:
// 
//     * Redistributions of source code must retain the above copyright notice, this list 
//         of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright notice, this 
//         list of conditions and the following disclaimer in the documentation and/or 
//         other materials provided with the distribution.
//     * Neither the name of the AntsAdventureGameCreator nor the names of its contributors 
//         may be used to endorse or promote products derived from this software without 
//         specific prior written permission.
// 
// 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 
// THE POSSIBILITY OF SUCH DAMAGE.
#include "XStdafx.h"
#include "XMainWindow.h"
#include <math.h>
#include "XRoomObject.h"
#include "XHitType.h"
#include "XVerbs.h"
#include "XVerb.h"
#include "XStatelessAction.h"
#include "XEntireLevelAction.h"
#include "XFolderTraversing.h"
#include "XDialogForLayout.h"
#include "XInventoryItem.h"
#include "XAnimation.h"
#include "XAnimations.h"
#include "RoomRegistry.h"
#include "Room.h"
#include "AntsApi.h"
#include "InventoryItems.h"
#include "InventoryItem.h"
#include "RoomRegistry.h"
#include "Choices.h"
#include "Inventory.h"
#include "VerbEnumeration.h"
#include "XGlobals.h"


QThread* g_guiThread = NULL;

XMainWindow::XMainWindow(QString startingRoom, QSize gameSize, QWidget* parent)
:QGraphicsView(parent)
, m_currentRoom(*this)
, m_threadForVariousGuiBlockingEvents(m_verbsGridGui, m_inventoryGui, m_currentRoom, m_commandLineGui, *this)
, m_threadForTimer(*this)
, m_isInNeedOfAReSort(false)
{
    qRegisterMetaType<SpecialAnimation>("SpecialAnimation");
    qRegisterMetaType<Choices>("Choices");


    m_startingRoom = startingRoom;
    m_isShowingDots = false;
    m_isShowingBoxes= false;
    m_isDisallowInput = true;
    m_isZbufferVisible = false;
    m_timerId = 0;
    m_isTimerNeedingToBeKilled = false;
    m_gameSize = gameSize;

    m_mouseMiddleMoveStart = QPoint(0,0);
    m_zbuffer = QImage(gameSize.width(), gameSize.width(), QImage::Format_RGB32);

    g_guiThread = QThread::currentThread();

    QGraphicsScene *scene = new QGraphicsScene(this);// del by parent
    scene->setItemIndexMethod(QGraphicsScene::NoIndex);
    setScene(scene);


    SetSize(gameSize);
    setWindowTitle(tr("Elastic Nodes"));

    QString currentPathBackBack = QDir::currentPath() + "\\..\\..";
    // generate Toom list
    if(QDir(currentPathBackBack).exists())
    {
        QStringList mastersAndSubanims = QDir(currentPathBackBack).entryList(FOLDERSONLY);
        for(int i=0;i<mastersAndSubanims.count();i++)
        {
            QString unsplitFolder = mastersAndSubanims.at(i);
            m_listOfRoomStrings.push_back(unsplitFolder);
        }
    }



    // start script, but it will quickly move to wait for restarts
    m_threadForVariousGuiBlockingEvents.StartThread();

    if(m_startingRoom.length())
    {
        //Api::MakeRoomActive(m_startingRoom);
        SwitchToRoomKeyword(m_startingRoom);
    }
    DumpSizes();
}

XMainWindow::~XMainWindow()
{
    m_threadForTimer.ExitProperly();
    XGlobals::DeleteAllNewedVariables();
}

void XMainWindow::resizeEvent(QResizeEvent * e )
{
    SetSize(e->size());
}

void XMainWindow::SetSize(QSize size)
{
    m_gameSize = size;
    scene()->setSceneRect(0, 0, size.width(), size.height());
    //setMinimumSize(size.width()/2, size.height()/2);

    UpdateRects();
}

void XMainWindow::UpdateRects()
{
    int pixelsAllocatedForVerbsAndCommand = 60;

    QFont font("times");
    font.setFixedPitch(true);
    font.setPointSize(8);
    m_verbsGridGui.SetFont(font);
    QFontMetrics fm(font);
    fm.height();


    // do rectForCommandLine
    QRect rectForCommandLine(0,0,m_gameSize.width(), fm.height());
    int heightWhereCommandLineStarts = m_gameSize.height() - pixelsAllocatedForVerbsAndCommand;
    rectForCommandLine.translate(0,heightWhereCommandLineStarts);
    m_commandLineGui.SetRect(rectForCommandLine);

    // resize verbs
    XDialogForLayout dialog(m_verbsGridGui.GetVerbStringList(), pixelsAllocatedForVerbsAndCommand - fm.height(),font);
    int widthOfVerbs = dialog.GetSmallestRectangleContainingAllVerbs(font).width();

    // do rectForVerbs
    QRect rectForVerbs(0,0,widthOfVerbs, pixelsAllocatedForVerbsAndCommand - fm.height());
    rectForVerbs.translate(0,heightWhereCommandLineStarts + fm.height());
    m_verbsGridGui.SetRect( rectForVerbs );

    // do InventoryItems
    QRect rectForInventory(0,0,m_gameSize.width() - widthOfVerbs, pixelsAllocatedForVerbsAndCommand - fm.height());
    rectForInventory.translate(0, heightWhereCommandLineStarts + fm.height());
    rectForInventory.translate(widthOfVerbs,0);
    m_inventoryGui.SetRect(rectForInventory);

    // do Choices
    QRect rectForChoices(0, 0, m_gameSize.width(), pixelsAllocatedForVerbsAndCommand);
    rectForChoices.translate(0,heightWhereCommandLineStarts);
    m_choicesGui.SetRect( rectForChoices);
}

void XMainWindow::keyPressEvent(QKeyEvent* e)
{
    switch (e->key()) {
    case Qt::Key_Up:
    case Qt::Key_Down:
    case Qt::Key_Left:
    case Qt::Key_Right:
        break;
    case Qt::Key_Plus:
        m_isZbufferVisible = !m_isZbufferVisible;
        break;
    case Qt::Key_Minus:
#ifdef _DEBUG
        m_choicesGui.DoChoicesDialog(this);
#endif
        break;
    case Qt::Key_Space:
        if(e->key()==Qt::Key_Space)
            ShowPopupMenu();
        break;
    default:
        QGraphicsView::keyPressEvent(e);
    }
}

void XMainWindow::mouseDoubleClickEvent(QMouseEvent* e)
{
    if(e->button() == Qt::RightButton)
    {
        m_commandLineGui.OnRightClick();
        m_commandLineGui.Execute(m_threadForVariousGuiBlockingEvents, e->x(), e->y());
    }
    else if(e->button() == Qt::LeftButton)
    {

        m_commandLineGui.Clear();
    }
    else if(e->button()  == Qt::MidButton)
    {
        ShowPopupMenu();
    }
}
void XMainWindow::OnChooseFolderFromMenu(QString keyword)
{
    SwitchToRoomKeyword(keyword);
}


void XMainWindow::CreateImageList(QVector<QImage>* imageList)
// create image list from both RoomObjects and Verbs
{
    if(!imageList) return;


}



void XMainWindow::ProcessGameEntities()
{
}

void XMainWindow::mousePressEvent(QMouseEvent* e)
{
    if(e->modifiers()!=0)
    {
        m_mouseMiddleMoveStart = QPoint(e->x(),e->y());
    }

    const QEvent::Type type = e->type();
    if(type == QEvent::MouseButtonPress)
    {
        if(e->button() == Qt::RightButton)
        {
            if(m_isDisallowInput)
            {
                m_commandLineGui.OnRightClick();

            }
        }
        else if(e->button() == Qt::LeftButton)
        {
            if(!m_isDisallowInput)
            {
                if(AntsApi::IsInChoicesMode())
                {
                    if(m_choicesGui.IsUpArrowVisible() && m_choicesGui.IsMouseOverUpArrow(e->pos()))
                    {
                        m_choicesGui.TriggerUpArrow();
                    }
                    else if(m_choicesGui.IsDownArrowVisible() && m_choicesGui.IsMouseOverDownArrow(e->pos()))
                    {
                        m_choicesGui.TriggerDownArrow();
                    }
                    else if(m_choicesGui.IsMouseOverChoices(e->pos()))
                    {
                        m_choicesGui.TriggerChoice(e->pos());
                    }
                }
                else
                {
                    if(m_inventoryGui.IsLeftArrowVisible() && m_inventoryGui.IsMouseOverLeftArrow(e->pos()))
                    {
                        m_inventoryGui.TriggerLeftArrow();
                    }
                    else if(m_inventoryGui.IsRightArrowVisible() && m_inventoryGui.IsMouseOverRightArrow(e->pos()))
                    {
                        m_inventoryGui.TriggerRightArrow();
                    }

                    else if(m_commandLineGui.IsOkToExecute())
                    {
                        m_commandLineGui.Execute(m_threadForVariousGuiBlockingEvents, e->x(), e->y());
                    }
                    else
                    {
                        m_commandLineGui.DoNextBestThingToExecute();
                    }
                }
            }
        }
        else if(e->button()  == Qt::MidButton)
        {
            ShowPopupMenu();
        }
    }
    else if(type == QEvent::MouseButtonRelease)
    {
    }
    else if(type == QEvent::MouseButtonDblClick)
    {

    }
    else if(type == QEvent::KeyPress)
    {
    }
    else if(type == QEvent::KeyRelease)
    {
    };
}


void XMainWindow::drawBackground(QPainter* painter, const QRectF &rect)
{
    m_draws++;
    Q_UNUSED(rect);

    // PartA - update state of rollovers based on QCursor
    int indexOfHighlightedSlot = -1;
    int indexOfHighlightedVerb = -1;
    int indexOfHighlightedObject = -1;

    QColor color;
    QPoint mousePos = mapFromGlobal(QCursor::pos());
    if(mousePos.x() < rect.width() && mousePos.y() < rect.height() && mousePos.x()>0 && mousePos.y()>0)
    {
        color = m_zbuffer.pixel(mousePos.x(),mousePos.y());
    }

    int i = color.green();

    switch(color.red())
    {
    case XHitType::Object:
        {
            indexOfHighlightedObject = i;
        }
        break;
    case XHitType::Verb:
        {
            indexOfHighlightedVerb = i;
        }
        break;
    case XHitType::InventorySlot:
        {
            indexOfHighlightedSlot = i;
        }
        break;
    case XHitType::ChoiceSlot:
        {
            m_choicesGui.SetHighlightedSlot(i);
        }
        break;
        //case XHitType::RightArrow:
        //case XHitType::LeftArrow:
    default:
        ;
        //	m_commandLineGui.SetRollover(QString(" ").arg(mousePos.x()).arg(mousePos.y()),0);

    }

    // use image instead of verb, because we are lazy
    if(indexOfHighlightedVerb !=-1)
    {
        XVerb* item = m_verbsGridGui.At(indexOfHighlightedVerb );
        QString displayName = item->DisplayName();
        m_commandLineGui.SetRollover(displayName, QString("%1").arg(indexOfHighlightedVerb+1));
    }

    if(indexOfHighlightedSlot !=-1)
    { 
        if(m_inventoryGui.IsInventoryItemAtSlot(indexOfHighlightedSlot))
        {
            const QPointer<XInventoryItem>& item = m_inventoryGui.GetInventoryItemAtSlot(indexOfHighlightedSlot);
            if(item.isNull())// if there is no inventory GetInventoryItemAtSlot  will return a null pointer
            {
                QString displayName = item->DisplayName();
                QString keyword = item->Keyword();
                m_commandLineGui.SetRollover(displayName, keyword);
            }
        }
    }

    if(indexOfHighlightedObject != -1)
    {
        XRoomObject* item = m_currentRoom.Items().At(indexOfHighlightedObject );
        QString displayName = item->GetDisplayName();
        QString keyword = item->Keyword();

        bool allowObjectInSentence = false;

        // in the case where we are looking for the second object of a Give command
        // then only allow object in sentence if object is GiveEnabled
        if(m_commandLineGui.GetSentence().VerbAsVerbEnumeration() == Give
            && m_commandLineGui.GetSentence().IsLookingForSecondObject())
        {
            if(item->IsGiveEnabled())
            {
                allowObjectInSentence = true;
            }
        }
        else
        {
            allowObjectInSentence = true;
        }

        if(allowObjectInSentence)
        {
            m_commandLineGui.SetRollover(displayName, keyword);
        }

    }

    if(indexOfHighlightedVerb ==-1 && indexOfHighlightedSlot==-1 && indexOfHighlightedObject==-1)
    {
        m_commandLineGui.SetRollover("","");
    }

    m_verbsGridGui.SetHighlightedVerb(indexOfHighlightedVerb);
    m_inventoryGui.SetHighlightedSlot(indexOfHighlightedSlot);





    // part 2 - Do the Drawing

    m_zbuffer.fill(0);
    QPainter zbuffer(&m_zbuffer);
    QPainter& p1 = m_isZbufferVisible? zbuffer : *painter;
    QPainter& p2 = m_isZbufferVisible? *painter : zbuffer;

    // set background to black
    if(m_roomName.length())
        p1.fillRect(rect,Qt::black);

    if(m_isInNeedOfAReSort)
    {
        m_currentRoom.Items().Sort();
        m_isInNeedOfAReSort = false;
    }

    // objects
    std::list<XRoomObjectPointer>::iterator iter = m_currentRoom.Items().Sorted().begin();
    for(; iter != m_currentRoom.Items().Sorted().end(); iter++)
    {
        iter->Get()->DrawIfVisible(p1,p2,qRgb(XHitType::Object,i,0), m_isShowingDots,  m_isShowingBoxes);
    }

    if(AntsApi::IsInChoicesMode())
    {
        // choices slots
        for(int i=0;i<m_choicesGui.Slots().Count();i++)
        {
            m_choicesGui.DrawSlotIfVisible(i,p1, p2, qRgb(XHitType::ChoiceSlot,i,0), m_isDisallowInput);
        }

        m_choicesGui.DrawDownArrowIfVisible(mousePos, p1,p2, qRgb(XHitType::BottomChoiceArrow,0,0) , m_isDisallowInput);
        m_choicesGui.DrawUpArrowIfVisible(mousePos, p1, p2, qRgb(XHitType::TopChoiceArrow,0,0) , m_isDisallowInput);

    }
    else
    {
        // verbs below objects
        for(int i= 0; i<m_verbsGridGui.Count();i++)
        {
            m_verbsGridGui.DrawVerbIfVisible(i, p1, p2, qRgb(XHitType::Verb,i,0), m_isDisallowInput);
        }

        // inventory slots
        for(int i=0;i<m_inventoryGui.Slots().Count();i++)
        {
            m_inventoryGui.Slots().DrawSlotIfVisible(i,p1, p2, qRgb(XHitType::InventorySlot,i,0));
        }

        m_inventoryGui.DrawRightArrowIfVisible(mousePos, p1,p2, qRgb(XHitType::RightInventoryArrow,0,0),m_isDisallowInput );
        m_inventoryGui.DrawLeftArrowIfVisible(mousePos, p1, p2, qRgb(XHitType::LeftInventoryArrow,0,0),m_isDisallowInput );

        // draw commandline
        m_commandLineGui.DrawCommandLineIfVisible(p1, m_isDisallowInput);

    }

    // speech on top of objects
    iter = m_currentRoom.Items().Sorted().begin();
    for(; iter != m_currentRoom.Items().Sorted().end(); iter++)
    {
        iter->Get()->DrawSpeechIfVisible(p1);
    }


    painter->setPen(Qt::red);
    painter->drawText(QPoint(0,170), QString("%1").arg(m_draws*25.0/m_ticks));
    if(m_ticks>100)
    {
        m_ticks=0;
        m_draws=0;
    }


}

QString CurrentPathTwoDotsKeyword(QString keyword)
{
    return QDir::currentPath() + "\\..\\..\\" + keyword;
}


void XMainWindow::ShowPopupMenu()
{
    QMenu menu;

    menu.addAction(new XStatelessAction("800x600", "On800x600", this, 0 ));// del by parent
    menu.addAction(new XStatelessAction("320x240", "On320x240", this, 0 ));//del by parent
    menu.addAction(new XStatelessAction("Switch To Room ...", "OnSwitchToRoomFromMenu", this, 0 ));// del by parent
    menu.addAction(new XStatelessAction("Show Room Object Dots", "OnShowRoomObjectDots", this, 0 ));//del by parent
    menu.addAction(new XStatelessAction("Show Room Object Boxes", "OnShowRoomObjectBoxes", this, 0 ));//del by parent

    for(int i=0;i<GetRoomRegistry().Count();i++)
    {
        QString keyword = GetRoomRegistry().At(i)->Folder();
        if(QFile::exists(CurrentPathTwoDotsKeyword(keyword)))
        {
            menu.addAction(new XEntireLevelAction(GetRoomRegistry().At(i)->Folder(), RoomGranularity, *this));// del by parent
        }
    }
    menu.addSeparator();

    if(m_roomName.length() && GetRoomRegistry().At(m_roomName))
    {
        QString lastName = "";
        for(int i=0;i<20;i++)
        {
            QString menuName = GetRoomRegistry().At(m_roomName)->OnDebugMenuExtension(i, true); // del by parent
            if(menuName.length())
            {
                if(lastName.length() && lastName == menuName)
                {
                    menu.addAction(new XStatelessAction("Duplicate Name - Aborting...", "OnDebugMenuExtension", this, i)); // del by parent
                    break;
                }
                else
                {
                    menu.addAction(new XStatelessAction(menuName, "OnDebugMenuExtension", this, i));// del by parent
                    lastName = menuName;
                }
            }
            else if(i > 0)
            {
                break;
            }
        }
    }


    menu.exec(QCursor::pos());
}

void XMainWindow::On320x240()
{
    SetSize(QSize(320,340));
}

void XMainWindow::On800x600()
{
    SetSize(QSize(800,600));
}

void XMainWindow::SwitchToRoomKeyword(QString keyword)
{
    QString folder = CurrentPathTwoDotsKeyword(keyword);
    EnterRoomFolder(folder);
}

void XMainWindow::SwitchToRoomFolder(QString folder)
{
    // exit room
    ExitRoom();

    // enter room
    EnterRoomFolder(folder);
}

void XMainWindow::EnterRoomFolder(QString mainFolder)
{
    XReceiver::SetIsSayingAbort(true);// this occurs within 10ms unless user themselves is doing a sleep
    Log::Threads("stopping timer thread");
    m_threadForTimer.ExitProperly();
    m_roomName = QDir(mainFolder).dirName();
    m_ticks = 0;
    m_draws = 0;

    m_currentRoom.SetKeyword(m_roomName);
    m_currentRoom.Items().Clear();
    m_inventoryGui.Items().Clear();
    m_verbsGridGui.Clear();

    m_verbsGridGui.AddNew("Walk", "Walk to AAA");
    m_verbsGridGui.AddNew("Talk", "Talk to AAA");
    m_verbsGridGui.AddNew("Examine", "Examine AAA");
    m_verbsGridGui.AddNew("Grab", "Grab AAA");
    m_verbsGridGui.AddNew("Cut", "Cut AAA|Cut AAA with BBB");
    m_verbsGridGui.AddNew("Swing", "Swing AAA");
    m_verbsGridGui.AddNew("Give", "Give AAA|Give AAA to BBB");
    m_verbsGridGui.AddNew("Use", "Use AAA|Use AAA with BBB");
    m_verbsGridGui.AddNew("Push", "Push AAA");
    m_verbsGridGui.AddNew("Pull", "Pull AAA");
    m_verbsGridGui.AddNew("Throw", "Throw AAA|Throw AAA at BBB");

    // make a collection with main room and all its resource rooms
    QVector<QString> listOfRooms = XRoom::ReturnListOfNamesOfRoomAndResourceRooms(m_roomName);

    for(int i=0;i<listOfRooms.size();i++)
    {
        QString roomName = listOfRooms[i];
        QString folder = CurrentPathTwoDotsKeyword(roomName);
        if(QDir(folder).exists())
        {
            QStringList mastersAndSubanims = QDir(folder).entryList(FOLDERSONLY);
            for(int i=0;i<mastersAndSubanims.count();i++)
            {
                QString unsplitFolder = mastersAndSubanims.at(i);
                QString trimmedFolder = mastersAndSubanims.at(i);
                trimmedFolder.remove("INVDEF(");
                trimmedFolder.remove("DEF(");
                trimmedFolder.remove("ANIM");
                trimmedFolder.remove(",");
                trimmedFolder.remove(")");
                QStringList stringList = trimmedFolder.split(" ", QString::SkipEmptyParts);

                // remove numerical prefix - if there is any
                bool hasPrefix = false;
                int orderingNumber = stringList[0].toInt(&hasPrefix);
                if(hasPrefix==true)
                {
                    stringList.pop_front();
                }

                if(stringList.count() ==1)
                {
                    // If string list contains only one string
                    // then folder must be either inventory or room object (not an animation)
                    QString keyword = stringList.at(0);


                    QString fullPath = folder + "/" + unsplitFolder;
                    if(stringList.at(0).contains("inv_"))
                    {
                        // inventory item folder
                        QPointer<XInventoryItem> inventoryItem = new XInventoryItem();
                        inventoryItem->SetKeyword(keyword);
                        inventoryItem->SetDisplayName(keyword);
                        inventoryItem->SetFullPath(fullPath);
                        inventoryItem->LoadImageFromFirstPngInFolder();
                        m_inventoryGui.Items().Add(inventoryItem);
                    }
                    else
                    {
                        // room object folder (not an animation)
                        QPointer<XRoomObject> roomObject = new XRoomObject(keyword, *this);
                        roomObject->SetParentWidget(this);
                        roomObject->SetIndex(m_currentRoom.Items().Count());// count = current last index + 1
                        roomObject->SetDisplayName(keyword);
                        roomObject->SetFullPath(fullPath);
                        if(hasPrefix)
                        {
                            roomObject->SetOrderingNumber(orderingNumber);
                        }

                        m_currentRoom.Items().Add(roomObject);
                    }
                }
                else if(stringList.count() > 1)
                {
                    // sub anim
                    QString keywordForRoomObject = stringList.at(0);

                    QString keywordForAnim = stringList.at(1);

                    int indexOfRoomObject = m_currentRoom.Items().IndexOf(keywordForRoomObject);
                    if(indexOfRoomObject !=-1)
                    {
                        m_currentRoom.Items().At(indexOfRoomObject)->AddAnimation(keywordForAnim, folder + "/" + unsplitFolder);
                    }
                }
            }
        }else
        {
            ASSERT(false && "Switched to room that has No folder in the File System!");
        }
    }
    UpdateRects();

    // we've added to the m_vector, but the m_sortedList isn't up to date
    UpdateRoomObjectOrder();

    m_threadForVariousGuiBlockingEvents.InitializeAPIRootVariables();
}


void XMainWindow::OnInitializeRootVariablesFinished()
{
    CallOnInitializeRoom();

    // setup redraws to occur periodically.

    //m_timerForOnEveryTick->start(g_timePerFrame);
    m_threadForTimer.StartTimer(m_roomName);
    // ^^ this will kick off the timer thread for OnEveryTick

    AntsApi::SetIsInChoicesMode(false);// enterroom does not open in choices mode
    m_verbsGridGui.SetVisible(false);
    m_inventoryGui.SetVisible(false);
    m_commandLineGui.SetVisible(false);
    m_isDisallowInput = true;
    m_threadForVariousGuiBlockingEvents.CallOnEnterRoom( m_roomName );
}

void XMainWindow::OnEnterRoomFinished()
{
    AntsApi::SetIsInChoicesMode(false);// main play does not open in choices mode.
    m_verbsGridGui.SetVisible(true);
    m_inventoryGui.SetVisible(true);
    m_commandLineGui.SetVisible(true);
    m_isDisallowInput = false;
}


void StandardRoomPreparation()
{
    // inventory items only become visible when you pick them up
    for(int i=0;i<AntsApi::GetInventory().Items().Count();i++)
    {
        AntsApi::GetInventory().Items().At(i).SetVisible(false);
    }

#ifdef NDEBUG
   // AntsApi::GetRoom().Objects().At("tester").SetVisible(false);
#endif

}


void XMainWindow::CallOnInitializeRoom()
{
    //Log("OnEveryTick");
    m_ticks++;

    try
    {
        QVector<QString> listOfRooms = XRoom::ReturnListOfNamesOfRoomAndResourceRooms(m_roomName);

        for(int i=0;i<listOfRooms.size();i++)
        {
            if(GetRoomRegistry().At(listOfRooms[i]) != NULL)
            {
                GetRoomRegistry().At(listOfRooms[i])->OnInitializeRoom(m_roomName);
            }
        }
    }
    catch(std::exception)
    {
    }
    catch(const char*)
    {
    }

    ::StandardRoomPreparation();
}

void XMainWindow::ExitRoom()
{
    m_threadForVariousGuiBlockingEvents.CallOnExitRoom();
}


void XMainWindow::RegularButBadTiming()
{

}

void XMainWindow::OnEveryTick(QString roomName)
{
    // When we enter a room, and destroy the gui-side object collection
    // it which means any access to the thread-side proxies will
    // generate exceptional gui-side signals.

    // so we set the script-threads to abort

    // but there might still be messages on the queue that
    // were sent before 'abort' was set.

    if(roomName == m_roomName)
    {
        //Log("OnEveryTick");
        m_ticks++;

        try
        {
            if(GetRoomRegistry().At(m_roomName))
            {
                GetRoomRegistry().At(m_roomName)->OnEveryTick();
            }
        }
        catch(std::exception)
        {
        }
        catch(const char*)
        {
        }
        scene()->update();
    }
}

void XMainWindow::OnDebugMenuExtension(int i)
{
    if(m_roomName.length())
    {
        m_threadForVariousGuiBlockingEvents.CallOnDebugMenuExtension(i);
    }
}

void XMainWindow::OnSwitchToRoomFromMenu(int)
{
    QFileDialog dialog(this);
    dialog.setFileMode(QFileDialog::DirectoryOnly); 
    if (dialog.exec())
    {
        QString folderName = dialog.selectedFiles().at(0);
        SwitchToRoomFolder(folderName);    
        scene()->invalidate();
        scene()->update();
    }
}


void XMainWindow::OnShowRoomObjectBoxes(int )
{
    m_isShowingBoxes = !m_isShowingBoxes;
}
void XMainWindow::OnShowRoomObjectDots(int )
{
    m_isShowingDots = !m_isShowingDots;
}

void XMainWindow::UpdateRoomObjectOrder()
{
    m_isInNeedOfAReSort = true;
}

void XMainWindow::DoChoices(Choices& ch, XRoomObject& objectToSayChosenText)
{
    m_choicesGui.SetChoices(ch);
    m_choicesGui.SetSpeaker(objectToSayChosenText);
    m_choicesGui.UpdateImages();
    m_choicesGui.SetVisible(true);
    SetDisallowInput(false);
    SetIsInChoicesMode(true);
}

void XMainWindow::SetDisallowInput(bool isDisallowInput)
{
    m_isDisallowInput = isDisallowInput;
}

QObject* XMainWindow::GetQObject()
{
    return this;
}

//helper function for stateless action
#include "CommandLine.h"
#include "KeywordRegistry.h"
#include "Verbs.h"
#include "GAmeWindow.h"
#include "Verb.h"
#include "XChoicesDialog.h"
void XMainWindow::DumpSizes()
{
    Log::DataSizes("Animation",sizeof(Animation));
    Log::DataSizes("Animations",sizeof(Animations));
    Log::DataSizes("Choices",sizeof(Choices));
    Log::DataSizes("ChoicesHelper",sizeof(ChoicesHelper));
    Log::DataSizes("CommandLine",sizeof(CommandLine));
    //	Log::DataSizes("GameWindow",sizeof(GameWindow));
    Log::DataSizes("Inventory",sizeof(Inventory));
    Log::DataSizes("InventoryItem",sizeof(InventoryItem));
    Log::DataSizes("InventoryItems",sizeof(InventoryItems));
    Log::DataSizes("KeywordRegistry",sizeof(KeywordRegistry));
    Log::DataSizes("Room",sizeof(Room));
    Log::DataSizes("RoomObject",sizeof(RoomObject));
    //Log::DataSizes("RoomObjects",sizeof(RoomObjects));
    Log::DataSizes("RoomRegistry",sizeof(RoomRegistry));
    Log::DataSizes("Verb",sizeof(Verb));
    Log::DataSizes("Verbs",sizeof(Verbs));
    Log::DataSizes("XAnimation",sizeof(XAnimation));
    //	Log::DataSizes("XAnimationFrame",sizeof(XAnimationFrame));
    Log::DataSizes("XAnimationFrameCollection",sizeof(XAnimationFrameCollection));
    Log::DataSizes("XAnimations",sizeof(XAnimations));
    Log::DataSizes("XChoicesDialog",sizeof(XChoicesDialog));
    Log::DataSizes("XChoicesSlotCollection",sizeof(XChoicesSlotCollection));
    Log::DataSizes("XCommandLine",sizeof(XCommandLine));
    Log::DataSizes("XDialogForLayout",sizeof(XDialogForLayout));
    Log::DataSizes("XEmitter",sizeof(XEmitter));
    Log::DataSizes("XEntireLevelAction",sizeof(XEntireLevelAction));
    Log::DataSizes("XFolderTraversing",sizeof(XFolderTraversing));
    Log::DataSizes("XFrameAnimationKeyword",sizeof(XFrameAnimationKeyword));
    Log::DataSizes("XGlobals",sizeof(XGlobals));
    Log::DataSizes("XImage",sizeof(XImage));
    Log::DataSizes("XInventory",sizeof(XInventory));
    Log::DataSizes("XInventoryItem",sizeof(XInventoryItem));
    Log::DataSizes("XInventoryItems",sizeof(XInventoryItems));
    Log::DataSizes("XInventorySlotCollection",sizeof(XInventorySlotCollection));
    Log::DataSizes("XMainWindow",sizeof(XMainWindow));
    Log::DataSizes("XReciever",sizeof(XReceiver));
    Log::DataSizes("XRoom",sizeof(XRoom));
    Log::DataSizes("XRoomObject",sizeof(XRoomObject));
    Log::DataSizes("XRoomObjectPointer",sizeof(XRoomObjectPointer));
    Log::DataSizes("XRoomObjects",sizeof(XRoomObjects));
    Log::DataSizes("XSentence",sizeof(XSentence));
    Log::DataSizes("XStatelessAction",sizeof(XStatelessAction));
    Log::DataSizes("XStringNumberCombo",sizeof(XStringNumberCombo));
    Log::DataSizes("XVerb",sizeof(XVerb));
    Log::DataSizes("XVerbs",sizeof(XVerbs));
    Log::DataSizes("XThreadForOnEnterRoomAndOnCommandLine",sizeof(XThreadForOnEnterRoomAndOnCommandLine));
    Log::DataSizes("XThreadForOnEveryTick",sizeof(XThreadForOnEveryTick));

}
